﻿using CommonlyUtils;
using ImClientApi.Utils;
using ImModels.Service.Models.Data;
using ImModels.View;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using System.Net.WebSockets;
using System.Security.Claims;

namespace ImClientApi.Controllers
{
    /// <summary>
    /// 聊天用户控制器
    /// </summary>
    public class UsersController : BaseAuthController
    {
        /// <summary>
        /// 根据企业注册时获得的秘钥+企业ID 上线 获取socket连接,并会返回接口权限
        /// 职位、电话、头像等 可传入 供显示
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        [AnyUser]
        public async Task<ResView<UserOnlineRes>> Online([FromBody] ReqView<UserOnlineReq> reqview)
        {
            #region 上线接口 判断 AppId 和 秘钥即可
            var enterId = reqview.AppId;
            this.Request.Headers.TryGetValue("Authorization", out StringValues headAuth);
            var enterDb = await DbUtils.DbHelper.GetOneAsync<Enterprise>(p => p.KID == enterId);
            if (enterDb == null || enterDb.KID == 0)
            {
                return new ResView<UserOnlineRes>() { code = 500, msg = "当前企业未开通IM功能，请开通后重试" };
            }

            var key = AESHelper.Encrypt(enterId + enterDb.Secret, ConfigUtils.AesKey, ConfigUtils.AesIv);
            if (key != headAuth)
            {
                return new ResView<UserOnlineRes>() { code = 302, msg = "参数鉴权错误" };
            }
            #endregion

            var reqUser = reqview.Data;

            var bizUserId = reqUser.BizUserId;
            if (bizUserId.IsNull())
            {
                return new ResView<UserOnlineRes>() { code = 500, msg = "用户ID不能为空" };
            }

            long sockId = Builder.GetNewSnowId();
            var itemDb = await DbUtils.DbHelper.GetOneAsync<Users>(p => p.EnterpriseId == reqview.AppId && p.BizUserId == bizUserId);
            if (itemDb == null || itemDb.KID == 0)
            {
                #region 不存在用户 新建一条
                var addDb = await DbUtils.DbHelper.AddItemAsync<Users>(new Users()
                {
                    KID = sockId,
                    States = 0,
                    IsDeleted = 0,
                    CreateTime = DateTime.Now,
                    LoginTime = DateTime.Now.ToStr(),
                    EnterpriseId = reqview.AppId,
                    JobName = reqUser.JobName,
                    IsAdmin = 0,
                    Account = reqUser.ContactTel,
                    ContactTel = reqUser.ContactTel,
                    FullName = reqUser.FullName,
                    NickName = reqUser.NickName,
                    HeadImg = reqUser.HeadImg,
                    UserInfo = reqUser.UserInfo,
                    BizUserId = bizUserId,
                    LoginPwd = ""
                });
                if (addDb == 0)
                {
                    return new ResView<UserOnlineRes>() { code = 500, msg = "用户信息初始化失败，请稍候再试" };
                }
                #endregion
            }
            else
            {
                #region 更新最新信息
                sockId = itemDb.KID;
                var upDb = await DbUtils.DbHelper.UpdateFieldsAsync<Users>(p => new Users()
                {
                    LoginTime = DateTime.Now.ToStr(),
                    JobName = reqUser.JobName,
                    Account = reqUser.ContactTel,
                    ContactTel = reqUser.ContactTel,
                    FullName = reqUser.FullName,
                    NickName = reqUser.NickName,
                    HeadImg = reqUser.HeadImg,
                    UserInfo = reqUser.UserInfo,
                    LoginPwd = ""
                }, p => p.KID == sockId);
                #endregion
            }

            #region 判断是否存在 系统消息会话 不存在 加一条
            var sysSessionDb = await DbUtils.DbHelper.GetOneAsync<MySession>(p => p.BizUserId == bizUserId && p.ToUserId == reqview.AppId.ToString() && p.IsGroup == 2);
            if (sysSessionDb == null || sysSessionDb.SessionId == 0)
            {
                #region 创建一个 系统会话
                MySessionLogic.CreateSession(new MySession()
                {
                    SessionId = reqview.AppId,//Builder.GetNewSnowId(),
                    EnterpriseId = reqview.AppId,
                    BizUserId = bizUserId,
                    ToUserId = reqview.AppId.ToString(),
                    IsGroup = 2,
                    FullName = "系统消息",
                    NickName = "",
                    HeadImg = ConfigUtils.GetConfigToString("SessionDefaultSysImage"),
                    IsTop = 1
                });
                #endregion
            }
            #endregion

            itemDb = await DbUtils.DbHelper.GetOneAsync<Users>(p => p.EnterpriseId == reqview.AppId && p.BizUserId == bizUserId);

            var wsUrl = ImHelper.PrevConnectServer(sockId, this.SrcIp);

            //组装jwt信息
            IEnumerable<Claim> claims = new Claim[] {
                        new Claim(nameof(JwtUserInfo.UserKid),sockId.ToString()),//会员id
                        new Claim(nameof(JwtUserInfo.UserName),itemDb.FullName),//会员名称
                        new Claim(nameof(JwtUserInfo.EnterpriseId),itemDb.EnterpriseId.ToString()),
                        new Claim(nameof(JwtUserInfo.BizUserID),reqUser.BizUserId),
                        new Claim(nameof(JwtUserInfo.EnterSecret),enterDb.Secret)
                    };

            var loginUser = new UserOnlineRes()
            {
                JwtInfo = JwtHepler.BuildJwtToken(claims),
                wsdata = new WebSocketView()
                {
                    WebSocketId = sockId,
                    WebSocketUrl = wsUrl,
                },
                user = itemDb
            };
            return new ResView<UserOnlineRes>() { code = 200, msg = "ok", data = loginUser };
        }

        /// <summary>
        /// ws重连
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView> WsReConn([FromBody] ReqView reqview)
        {
            var jwtUser = GetUseByJwtToken();

            if (jwtUser.EnterpriseId != reqview.AppId.ToString())
            {
                return await ReturnFailed(302, "当前Token和登录用户信息不匹配，请核对修改后重试");
            }

            var wsUrl = ImHelper.PrevConnectServer(Convert.ToInt64(jwtUser.UserKid), this.SrcIp);

            return new ResView() { code = 200, msg = "ok", data = wsUrl };
        }

        /// <summary>
        /// 修改名称 可以单独修改
        /// 修改的json data里面的key对应字段 支持 FullName NickName HeadImg UserInfo ContactTel 其余字段不允许修改
        /// 且 字典里面 必须包含 BizUserID 作为更新条件
        /// </summary>
        /// <param name="reqview"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResView> UpName([FromBody] ReqView<Dictionary<string, object>> reqview)
        {
            var cannUpKeys = "bizuserid,fullname,nickname,headimg,userinfo,contacttel".Split(',');

            var bizUserId = "";

            var upDic = new Dictionary<string, object>();
            foreach (var item in reqview.Data)
            {
                if (item.Key.ToLower() == "bizuserid")
                {
                    bizUserId = item.Value.ToString();
                }
                if (cannUpKeys.Contains(item.Key.ToLower()) && !item.Value.IsNull())
                {
                    upDic[item.Key] = item.Value.ToString();
                }
            }
            if (string.IsNullOrWhiteSpace(bizUserId) || upDic.Count() == 0)
            {
                return new ResView() { code = 500, msg = "条件必须包含BizUserID 和 需修改的信息值" };
            }
            upDic[nameof(Users.EnterpriseId)] = reqview.AppId;

            var upDb = await DbUtils.DbHelper.UpdateByDicAsync<Users>(upDic, nameof(Users.BizUserId), nameof(Users.EnterpriseId));
            return new ResView()
            {
                code = upDb > 0 ? 200 : 500,
                msg = upDb > 0 ? "更新成功" : "更新失败"
            };
        }

    }
}
